
(use ./common)
(defn quad (p0 p1 p2 t)
  (def s (- 1 t))
  (+ (* s s p0) (* 2 s t p1) (* t t p2)))
(defn cubic (a b c d x)
  (def p (- (- d c) (- a b)))
     (+ (* x (+ (* x (+ (* x p) (- a b p))) (- c a))) b))

(defn cubic-noise (&opt seed)
  (default seed 0)
  (def rng (fn rng (&opt & etc) (math/rng (buffer ;etc seed))))
  (def rand @[])
  (defn new-i (i)
    (pp i)
    (pp [[rand i] rng (rng i)])
    (pp (get rand i))
    ()
    (set (rand i) (:uniform (rng i)))) #returns value
  (defn closest (i)
    (math/floor i))
  (defn get-i (i)
    #(cond (get rand i) (rand i)
    #      (int? i) (new-i i)
           (let (closest-key
                 (math/floor i)
                 closest-key+1
                 (inc closest-key)
                 closest-key-1
                 (dec closest-key)
                 closest-key+2
                 (inc closest-key+1)
                 t
                 (/ (- i closest-key) (- closest-key+1 closest-key) ) #[0,1]
                 x1
                 (:uniform (rng closest-key))
                 x2
                 (:uniform (rng closest-key+1))
                 x3
                 (:uniform (rng closest-key+2))
                 x0
                 (:uniform (rng closest-key-1)))
             (cubic x0 x1 x2 x3 t)))
  get-i)

(defn cubic-noise-2d (&opt seed1 seed2)
  (default seed1 0)
  (default seed2 1337)
  (def [get-x get-y] (map cubic-noise [seed1 seed2]))
  (fn get-x-y (&opt x y)
    (default x 0) (default y 0)
    (lerp (* (get-x x) (get-y y)))))


(defn disp-hmap ()
(def c (cubic-noise-2d))
(def m @[])
(for y 0 100
  (def l @[]) (set (m y) l)
     (for x 0 200
       (set (l x)
            (c (* .2 x)(* .2 y)))))
 (print ;(flatten (interpose "\n" (map (. map |(string (RGB256 $ $ $ :fg) "#")) k)))))

#second kind of quad noise is unpredictablish and also
##TODO: fix discontinuities in function (use a cubic instead of a quad?)
#(defn quad-noise* (&opt seed)
#  (default seed 0)
#  (def rng (math/rng seed))
#  (def rand @[])
#  (defn new-i (i)
#    (pp i)
#    (pp [[rand i] rng ])
#    (pp (get rand i))
#    (set (rand i) (:uniform rng))) #returns value
#  (defn closest (i)
#    (math/floor i))
#  (defn inoset (k)
#    (if (get rand k) (rand k)
#        (set (rand k) (:uniform rng))))
#  (defn get-i (i)
#    (cond (get rand i) (rand i)
#          (int? i) (new-i i)
#           (let (closest-key
#                 (closest i)
#                 closest-key+1
#                 (inc closest-key)
#                 closest-key-1
#                 (dec closest-key)
#                 t
#                 (/ (- i closest-key-1) (- closest-key+1 closest-key-1)) #always 2?
#                 x1
#                 (inoset closest-key)
#                 x2
#                 (inoset closest-key+1)
#                 x0
#                 (inoset closest-key-1)
#                  )
#             (quad x0 x1 x2 t))))
#  get-i)
